using System;
using System.Collections;
using SMS.SMPPClient.PDU;

namespace SMS.SMPPClient.PDU.Outgoing
{
    /// <summary>
    /// PDU to replace a previously submitted short message that hasn't been delivered.
    /// The match is based on the message_id and source addresses of the original message.
    /// </summary>
    public class SMPPReplaceSM : MessageLCD4
    {
        private string _MessageID;
        private string _ScheduleDeliveryTime;
        private string _ValidityPeriod;
        private byte _SMDefaultMessageID;
        private object _ShortMessage;

        /// <summary>
        /// Creates a replace_sm PDU.
        /// </summary>
        /// <param name="messageID">SMSC message ID of the message to be replaced. This must
        /// be the message ID of the original message.</param>
        /// <param name="sourceAddrTON">Type of Number. This must match that supplied in the
        /// corresponding submit_sm request.</param>
        /// <param name="sourceAddrNPI">Numbering Plan Indicator.  This must match that
        /// supplied in the original request.</param>
        /// <param name="sourceAddress">Originating address. This must match that supplied in
        /// the original request.</param>
        /// <param name="scheduleDeliveryTime">New scheduled delivery time for the short
        /// message.  Set to null, if updating of the original scheduled delivery
        /// time is not desired.</param>
        /// <param name="validityPeriod">New expiration time for the short message. Set
        /// to null, if updating of the original expiration time is not required.</param>
        /// <param name="registeredDelivery">New registered delivery parameter setting.
        /// </param>
        /// <param name="smDefaultMsgID">New pre-defined (canned) message identifier.  Set
        /// to 0 if not using.
        /// </param>
        /// <param name="shortMessage">New short message to replace existing message.
        /// </param>
        public SMPPReplaceSM(string messageID, TONType sourceAddrTON,
                                NPIType sourceAddrNPI, string sourceAddress,
                                string scheduleDeliveryTime, string validityPeriod,
                                RegisteredDeliveryType registeredDelivery,
                                byte smDefaultMsgID, object shortMessage)
            : base(registeredDelivery, sourceAddrTON,
                sourceAddrNPI, sourceAddress)
        {
            if (messageID != null)
            {
                if (messageID.Length <= MSG_LENGTH)
                    _MessageID = messageID;
                else
                    throw new ArgumentOutOfRangeException(
                        "Message ID must be <= " + MSG_LENGTH + " characters.");
            }
            else
                _MessageID = "";

            if (scheduleDeliveryTime != null)
            {
                if (scheduleDeliveryTime == "" ||
                    scheduleDeliveryTime.Length == DELIVERY_TIME_LENGTH)
                    _ScheduleDeliveryTime = scheduleDeliveryTime;
                else
                    throw new ArgumentException(
                        "Scheduled delivery time not in correct format.");
            }
            else
                _ScheduleDeliveryTime = "";


            if (validityPeriod != null)
            {
                if (validityPeriod == "" ||
                    validityPeriod.Length == VALIDITY_PERIOD_LENGTH)
                    _ValidityPeriod = validityPeriod;
                else
                    throw new ArgumentException(
                        "Validity period not in correct format.");
            }
            else
                _ValidityPeriod = "";

            _SMDefaultMessageID = smDefaultMsgID;
            _ShortMessage = shortMessage;
            _CommandStatus = 0;
            _CommandID = CommandIDType.replace_sm;
        }

        /// <summary>
        /// Generates the hex encoded bytes for a replace_sm PDU.
        /// </summary>
        public override System.Byte[] GetMSBHexEncoding()
        {
            ArrayList pdu = GetPDUHeader();

            pdu.AddRange(ArrayCopyWithNull(
                System.Text.Encoding.ASCII.GetBytes(_MessageID)));

            pdu.Add((byte)_SourceAddrTON);
            pdu.Add((byte)_SourceAddrNPI);

            pdu.AddRange(ArrayCopyWithNull(
                System.Text.Encoding.ASCII.GetBytes(_SourceAddress)));
            pdu.AddRange(ArrayCopyWithNull(
                System.Text.Encoding.ASCII.GetBytes(_ScheduleDeliveryTime)));
            pdu.AddRange(ArrayCopyWithNull(
                System.Text.Encoding.ASCII.GetBytes(_ValidityPeriod)));

            pdu.Add((byte)_RegisteredDelivery);
            pdu.Add(_SMDefaultMessageID);

            byte[] msg;

            if (_ShortMessage == null)
                msg = new Byte[] { 0x00 };
            else if (_ShortMessage is string)
                msg =
                    System.Text.Encoding.ASCII.GetBytes((string)_ShortMessage);
            else if (_ShortMessage is byte[])
                msg = (byte[])_ShortMessage;
            else
                throw new ArgumentException(
                    "Short Message must be a string or byte array.");

            if (msg.Length >= MessageLCD2.SHORT_MESSAGE_LIMIT)
                throw new ArgumentException(
                    "Short message cannot be longer than " +
                    MessageLCD2.SHORT_MESSAGE_LIMIT + " octets.");

            pdu.Add((byte)msg.Length);
            pdu.AddRange(msg);

            return EncodePDUForTransmission(pdu);
        }
    }
}

